package servlet;

import javax.naming.NamingException;

import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.Stack;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import fr.ginvest.entity.Administrateur;
import fr.ginvest.entity.Angel;
import fr.ginvest.entity.Article;
import fr.ginvest.entity.Article.Visibilite;
import fr.ginvest.entity.Avancement;
import fr.ginvest.entity.Club;
import fr.ginvest.entity.Commentaire;
import fr.ginvest.entity.Demande;
import fr.ginvest.entity.DemandeAngelClub;
import fr.ginvest.entity.DemandeAngelClub.Objet;
import fr.ginvest.entity.DemandeClubAmi;
import fr.ginvest.entity.Fondateur;
import fr.ginvest.entity.GroupeInvestisseur;
import fr.ginvest.entity.Investisseur;
import fr.ginvest.entity.Investisseur.ConnectionReseau;
import fr.ginvest.entity.Investisseur.Etat;
import fr.ginvest.entity.Investisseur.Genre;
import fr.ginvest.entity.Investisseur.Type;
import fr.ginvest.entity.Participation;
import fr.ginvest.entity.Participation.ENTANTQUE;
import fr.ginvest.entity.Startup;
import fr.ginvest.interfaces.AdministrateurFacadeRemote;
import fr.ginvest.interfaces.AngelFacadeRemote;
import fr.ginvest.interfaces.ArticleFacadeRemote;
import fr.ginvest.interfaces.AvancementFacadeRemote;
import fr.ginvest.interfaces.ClubFacadeRemote;
import fr.ginvest.interfaces.CommentaireFacadeRemote;
import fr.ginvest.interfaces.DemandeAngelClubFacadeRemote;
import fr.ginvest.interfaces.DemandeClubAmiFacadeRemote;
import fr.ginvest.interfaces.DemandeFacadeRemote;
import fr.ginvest.interfaces.FondateurFacadeRemote;
import fr.ginvest.interfaces.GroupeInvestisseurFacadeRemote;
import fr.ginvest.interfaces.InvestisseurFacadeRemote;
import fr.ginvest.interfaces.ParticipationFacadeRemote;
import fr.ginvest.interfaces.StartupFacadeRemote;

@SuppressWarnings("unused")
public class Controller extends HttpServlet {
	private static final Logger LOGGER = Logger.getLogger(Controller.class);
	
	Investisseur invest;
	Commentaire commentaire;
	Article article;
	
	InitialContext ctx;
	
	InvestisseurFacadeRemote investRemote;
	CommentaireFacadeRemote commentaireRemote;
	ArticleFacadeRemote articleRemote;

	private static final long serialVersionUID = 1L;
	
	public Controller() {
		super();
	}
	
	public void destroy() {
		super.destroy(); // Just puts "destroy" string in log
		// Put your code here
	}
	
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String opt = request.getParameter("action");
		Integer option = 0;
		if (opt == null)
			option = -1;
		else
			option = Integer.parseInt(opt);
		
		switch (option) {
		case 1:
			processRequest(request, response);
			break;
		case 2:
			try {
				getDetailArticle(request, response);
			} catch (ParseException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			break;
		case 5:
			try {
				visitOneProfil(request, response);
			} catch (ParseException e1) {
				e1.printStackTrace();
			}
			break;
		case 6:
			backProfil(request, response);
			break;
		default:
			request.getRequestDispatcher("/index.jsp").forward(request,
					response);
			break;
		}
	}
	
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String opt = request.getParameter("action");
		Integer option = 0;
		if (opt == null)
			option = -1;
		else
			option = Integer.parseInt(opt);
		switch (option) {
		case 1:
			processRequest(request, response);
			break;
		case 2:
			insertArticle(request, response);
			break;

		case 3:
			insertCommentaire(request, response);
			break;
		default:
			request.getRequestDispatcher("/index.jsp").forward(request,
					response);
			break;
		}
	}

	// connexion d'un utilisateur

	protected void processRequest(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		LOGGER.info("Login information: ");
		boolean success = false;
		String pwd = request.getParameter("pwd");
		String login = request.getParameter("login");
		HttpSession session = request.getSession();
		Club myClub = null;
		
		LOGGER.info("Type: Investisseur  Login: " + login);
		
		Investisseur invest = investRemote.authenticate(login, pwd);
		if((invest!=null) && !(invest.getType().equals(Type.GROUPE))){
			success = true;
			invest.setConnectionReseau(ConnectionReseau.OUI);
			invest = investRemote.updateInvestisseur(invest);
			session.setAttribute("investorType", invest.getType());
			LOGGER.info("Investor type: " + invest.getType());
			boolean isAngel= false;
			boolean isPresident = false;
			boolean hasClub = false;
			boolean isFounder = false;
			if(invest.getType().equals(Type.ANGEL)){
				isAngel = true;
				myClub = ((Angel)invest).getMyClub();
				if(myClub != null){
					isPresident = true;
					hasClub = true;
					session.setAttribute("myClubId", myClub.getId());
				}
			} else if(Type.FONDATEUR.equals(invest.getType())) {
				isFounder = true;
			}
			session.setAttribute("isAngel", isAngel);
			session.setAttribute("isFounder", isFounder);
			session.setAttribute("isPresident", isPresident);
			session.setAttribute("hasClub", hasClub);
			session.setAttribute("investor", invest);
			
			Collection<Article> listAllToutPublics = articleRemote.findAllToutPublic();
			Collection<Article> listAllPublics = articleRemote.findAll();
			Collection<Article> listMyArticles = articleRemote.findArticleOfInvestisseur(invest);
			Collection<Club> listMyClubs = null;
			if(isAngel){
				 listMyClubs = ((Angel)invest).getClubs();
				 if(myClub!=null)
					 listMyClubs.add(myClub);
			}
			session.setAttribute("articleToutPublic", listAllToutPublics);
			session.setAttribute("allArticle", listAllPublics);
			session.setAttribute("myArticle", listMyArticles);
			session.setAttribute("myClubs", listMyClubs);
			session.setAttribute("myGroupes", invest.getGroupes());
		}
		
		if (!success) {
			String message = "Login et/ou mot de passe incorrect";
			request.setAttribute("errorMessage", message);
			LOGGER.info("Login or password is incorrect.");
			request.getRequestDispatcher("/index.jsp").forward(request,response);
		} else {
			LOGGER.info("Login is successful.");
			
			session.setAttribute("user", invest);
			putInvestSession(session);
			request.getRequestDispatcher("/profil.jsp").forward(request,response);
		}
	}
	
	private void putInvestSession(HttpSession session) {
		Collection<Investisseur> listInvest = investRemote.findAll();
		session.setAttribute("listInvest", listInvest);
	}
	
	// Insertion d'un nouvel club
	
	protected void insertCommentaire(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		
		HttpSession session = request.getSession(true);
		String libelle = request.getParameter("libelle");
		int auteurId = Integer.parseInt(request.getParameter("idInvestisseur").toString());
		Long articleId = Long.parseLong(request.getParameter("idArticle").toString());
		Article article = articleRemote.findArticleById(articleId);
		Investisseur invest = investRemote.findInvestisseurById(auteurId);
		Commentaire commentaire = new Commentaire();
		commentaire.setArticle(article);
		commentaire.setInvestisseur(invest);
		commentaire.setLibelle(libelle);
		commentaire.setDateCreation(new java.util.Date());
		
		commentaire = commentaireRemote.addCommentaire(commentaire);
		
		article = articleRemote.findArticleById(articleId);
		Investisseur auteur = article.getInvestisseur();
		Set<Commentaire> listCommentaires = article.getCommentaires();
		
		session.setAttribute("article", article);
		session.setAttribute("auteur", auteur);
		session.setAttribute("listCommentaires", listCommentaires);
		
		request.getRequestDispatcher("/article_detail.jsp").forward(request, response);
	}

	// Insertion d'un nouvel article
	
	@SuppressWarnings("unchecked")
	protected void insertArticle(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		Boolean error = false;
		
		HttpSession session = request.getSession(true);
		Visibilite visibilite;
		String title = request.getParameter("title").toUpperCase();
		String resume = request.getParameter("resume");
		String visibility = request.getParameter("visibilite");
		if(visibility.equals("TP"))
			visibilite = Visibilite.TOUT_PUBLIC;
		else
			visibilite = Visibilite.PUBLIC;
		String articleText = request.getParameter("article");
		Investisseur invest2 = (Investisseur)session.getAttribute("user");
		article = new Article();
		article.setTitre(title);
		article.setResume(resume);
		article.setDescription(articleText);
		article.setDateCreation(new java.util.Date());
		article.setVisibilite(visibilite);
		
		article.setInvestisseur(invest2);
		
		article = articleRemote.addArticle(article);
		
		if(visibility.equals("TP")){
			Collection<Article> listAllTouPublics = (Collection<Article>)session.getAttribute("articleToutPublic");
			listAllTouPublics.add(article);
			session.removeAttribute("articleToutPublic");
			session.setAttribute("articleToutPublic", listAllTouPublics);
		}
		Collection<Article> listAllPublics = (Collection<Article>)session.getAttribute("allArticle");
		listAllPublics.add(article);
		Collection<Article> listMyArticles = (Collection<Article>)session.getAttribute("myArticle");
		listMyArticles.add(article);
		
		session.removeAttribute("allArticle");
		session.setAttribute("allArticle", listAllPublics);
		session.removeAttribute("myArticle");
		session.setAttribute("myArticle", listMyArticles);
		
		request.getRequestDispatcher("/profil.jsp").forward(request, response);
	}

	// prendre les details d'un article
	
	protected void getDetailArticle(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException,
			ParseException {
		
		HttpSession session = request.getSession(true);
		Object user = session.getAttribute("user");
		if(user!=null){
			String idart = request.getParameter("wart");
			if(idart !=null){
				Long idArt = Long.parseLong(idart);
				String test= request.getParameter("pirate++");
				System.out.println(test + "      " + test);
				Article article = articleRemote.findArticleById(idArt);
				Investisseur auteur = article.getInvestisseur();
				Set<Commentaire> listCommentaires = article.getCommentaires();
				
				session.setAttribute("article", article);
				session.setAttribute("auteur", auteur);
				session.setAttribute("listCommentaires", listCommentaires);
				
				request.getRequestDispatcher("/article_detail.jsp").forward(request, response);
			}
			else{
				request.getRequestDispatcher("/index.jsp").forward(request, response);
			}
		}
		else{
			request.getRequestDispatcher("/index.jsp").forward(request, response);
		}
	}
		
	protected void visitOneProfil(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException,
			ParseException {
		HttpSession session = request.getSession(true);
		Boolean success = true;
		String idinv = request.getParameter("wart");
		if(idinv != null){
			Integer idInv = Integer.parseInt(idinv);
			Investisseur invest = investRemote.findInvestisseurById(idInv);
			if(invest != null){
				Club myClub = null;
				session.setAttribute("visite", true);
				boolean isAngel= false;
				
				if(invest.getType().equals(Type.ANGEL)){
					isAngel = true;
					myClub = ((Angel)invest).getMyClub();
					if(myClub != null){
						session.setAttribute("myClubId", myClub.getId());
					}
				}
				session.setAttribute("isAngel", isAngel);
				session.setAttribute("investor", invest);
		
				Collection<Article> listAllToutPublics = articleRemote.findAllToutPublic();
				Collection<Article> listAllPublics = articleRemote.findAll();
				Collection<Article> listMyArticles = articleRemote.findArticleOfInvestisseur(invest);
				Collection<Club> listMyClubs = null;
				if(isAngel){
					 listMyClubs = ((Angel)invest).getClubs();
					 if(myClub!=null)
						 listMyClubs.add(myClub);
				}
				session.setAttribute("articleToutPublic", listAllToutPublics);
				session.setAttribute("allArticle", listAllPublics);
				session.setAttribute("myArticleVisite", listMyArticles);
				session.setAttribute("myClubsVisite", listMyClubs);
				session.setAttribute("myGroupesVisite", invest.getGroupes());
					
				request.getRequestDispatcher("/profil.jsp").forward(request, response);
			}
			else{
				request.getRequestDispatcher("/index.jsp").forward(request, response);
			}
		}
		else{
			request.getRequestDispatcher("/index.jsp").forward(request, response);
		}
	}
	
	protected void backProfil(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		
		request.getSession(true).removeAttribute("visite");
		
		
		request.getRequestDispatcher("/profil.jsp").forward(request,response);
	}
	
	public void init() throws ServletException {
		try {
			ctx = new InitialContext();
		    ctx.addToEnvironment(InitialContext.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory");
		    ctx.addToEnvironment(InitialContext.URL_PKG_PREFIXES,"org.jboss.naming:org.jnp.interfaces");
		    ctx.addToEnvironment(InitialContext.PROVIDER_URL,"jnp://localhost:1099");
		    
			investRemote = (InvestisseurFacadeRemote)ctx.lookup("GInvest/InvestisseurFacade/remote");
			commentaireRemote = (CommentaireFacadeRemote)ctx.lookup("GInvest/CommentaireFacade/remote");
			articleRemote = (ArticleFacadeRemote)ctx.lookup("GInvest/ArticleFacade/remote");
		} catch (NamingException e) {
			e.printStackTrace();
		}
	}

}